﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Web;

namespace WebSite.Web.Models
{
    public class RandomCodeInfo
    {
        /// <summary>
        /// 生成图片验证码
        /// </summary>
        /// <param name="nLen">验证码的长度</param>
        /// <param name="strKey">输出参数，验证码的内容</param>
        /// <returns>图片字节流</returns>
        public byte[] GenerateVerifyImage(int nLen, ref string strKey)
        {
            int nBmpWidth = 13 * nLen + 5;
            int nBmpHeight = 25;
            System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(nBmpWidth, nBmpHeight);
            // 1. 生成随机背景颜色
            int nRed, nGreen, nBlue;  // 背景的三元色
            System.Random rd = new Random((int)System.DateTime.Now.Ticks);
            nRed = rd.Next(255) % 128 + 128;
            nGreen = rd.Next(255) % 128 + 128;
            nBlue = rd.Next(255) % 128 + 128;
            // 2. 填充位图背景
            System.Drawing.Graphics graph = System.Drawing.Graphics.FromImage(bmp);
            graph.FillRectangle(new SolidBrush(System.Drawing.Color.FromArgb(nRed, nGreen, nBlue))
             , 0
             , 0
             , nBmpWidth
             , nBmpHeight);

            // 3. 绘制干扰线条，采用比背景略深一些的颜色
            int nLines = 3;
            System.Drawing.Pen pen = new System.Drawing.Pen(System.Drawing.Color.FromArgb(nRed - 17, nGreen - 17, nBlue - 17), 2);
            for (int a = 0; a < nLines; a++)
            {
                int x1 = rd.Next() % nBmpWidth;
                int y1 = rd.Next() % nBmpHeight;
                int x2 = rd.Next() % nBmpWidth;
                int y2 = rd.Next() % nBmpHeight;
                graph.DrawLine(pen, x1, y1, x2, y2);
            }
            // 采用的字符集，可以随即拓展，并可以控制字符出现的几率
            string strCode = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
            // 4. 循环取得字符，并绘制
            string strResult = "";
            for (int i = 0; i < nLen; i++)
            {
                int x = (i * 13 + rd.Next(3));
                int y = rd.Next(4) + 1;
                // 确定字体
                System.Drawing.Font font = new System.Drawing.Font("Courier New",
                 12 + rd.Next() % 4,
                 System.Drawing.FontStyle.Bold);
                char c = strCode[rd.Next(strCode.Length)];  // 随机获取字符
                strResult += c.ToString();
                // 绘制字符
                graph.DrawString(c.ToString(),
                 font,
                 new SolidBrush(System.Drawing.Color.FromArgb(nRed - 60 + y * 3, nGreen - 60 + y * 3, nBlue - 40 + y * 3)),
                 x,
                 y);
            }
            // 5. 输出字节流
            System.IO.MemoryStream bstream = new System.IO.MemoryStream();
            bmp.Save(bstream, System.Drawing.Imaging.ImageFormat.Jpeg);
            bmp.Dispose();
            graph.Dispose();
            strKey = strResult;
            byte[] byteReturn = bstream.ToArray();
            bstream.Close();
            return byteReturn;
        }
        private const double PI = 3.1415926535897932384626433832795;
        private const double PI2 = 6.283185307179586476925286766559;
        /// <summary>
        /// 正弦曲线Wave扭曲图片
        /// </summary>
        /// <param name="srcBmp"></param>
        /// <param name="bXDir"></param>
        /// <param name="nMultValue">波形的幅度倍数</param>
        /// <param name="dPhase">波形的起始相位，取值区间[0-2*PI)</param>
        /// <returns></returns>
        public System.Drawing.Bitmap TwistImage(Bitmap srcBmp, bool bXDir, double dMultValue, double dPhase)
        {
            System.Drawing.Bitmap destBmp = new Bitmap(srcBmp.Width, srcBmp.Height);
            // 将位图背景填充为白色
            System.Drawing.Graphics graph = System.Drawing.Graphics.FromImage(destBmp);
            graph.FillRectangle(new SolidBrush(System.Drawing.Color.White), 0, 0, destBmp.Width, destBmp.Height);
            graph.Dispose();

            double dBaseAxisLen = bXDir ? (double)destBmp.Height : (double)destBmp.Width;
            for (int i = 0; i < destBmp.Width; i++)
            {
                for (int j = 0; j < destBmp.Height; j++)
                {
                    double dx = 0;
                    dx = bXDir ? (PI2 * (double)j) / dBaseAxisLen : (PI2 * (double)i) / dBaseAxisLen;
                    dx += dPhase;
                    double dy = Math.Sin(dx);
                    // 取得当前点的颜色
                    int nOldX = 0, nOldY = 0;
                    nOldX = bXDir ? i + (int)(dy * dMultValue) : i;
                    nOldY = bXDir ? j : j + (int)(dy * dMultValue);
                    System.Drawing.Color color = srcBmp.GetPixel(i, j);
                    if (nOldX >= 0 && nOldX < destBmp.Width && nOldY >= 0 && nOldY < destBmp.Height)
                    {
                        destBmp.SetPixel(nOldX, nOldY, color);
                    }
                }
            }
            return destBmp;
        }


    }
}